#include "StdAfx.h"
#include "SetupThread.h"
#include <shellapi.h>

CSetupThread::CSetupThread(void):
m_ExitEvent(NULL),
m_pCallBack(NULL),
m_nSetupTimeout(120),
m_bPause(false),
m_pPostCount(NULL)
{
}

CSetupThread::~CSetupThread(void)
{
	Cancel();
}

void CSetupThread::Start(ITaskEvent* pCallBack,CPostCount* pPostCount)
{
	if(pCallBack)
	{
		m_pCallBack = pCallBack;
		m_ExitEvent = CreateEvent(NULL,TRUE,FALSE,L"setupevent");
		if(m_ExitEvent)
		{
			Create(TRUE);
		}
	}
	if(pPostCount)
		m_pPostCount = pPostCount;
}
void CSetupThread::Cancel()
{
	if(m_ExitEvent)
	{
		SetEvent(m_ExitEvent);
		CloseHandle(m_ExitEvent);
		m_ExitEvent = NULL;
		if(m_hThread)
		{
			DestroyThread();
		}
	}
	
}

UINT __stdcall CSetupThread::DefThreadProc()
{
	while(m_ExitEvent != NULL && WAIT_TIMEOUT == WaitForSingleObject(m_ExitEvent,1000))
	{
		SETUPSTRUCT setup;
		if(TRUE == GetSetupTask(setup) && m_bPause == false)
		{
			BOOL bRes = RunExe(setup.strPath);
			if(m_pCallBack)
				m_pCallBack->OnSetupCompleteCallBack(setup.strTaskNo,bRes);
			/*if(bRes)
			{
				if(m_pPostCount)
				{
					CStdString strUrl = MATERIAL_POSTCONT_SETUPSUCCESSED_ADDRESS;
					strUrl += setup.strTaskNo;
					strUrl += MATERIAL_POSTCONT_TYPE;
					m_pPostCount->AddPostCount(strUrl);
				}
			}*/
		}
	}
	return 0;
}

void CSetupThread::AddSetupTask(CStdString strTaskNo,CStdString strPath)
{
	CAutoLock AutoLock(m_csSetupList);
	SETUPSTRUCT setup;
	setup.strTaskNo = strTaskNo;
	setup.strPath = strPath;
	m_vSetupList.push_back(setup);
}

BOOL CSetupThread::GetSetupTask(SETUPSTRUCT& setup)
{
	CAutoLock AutoLock(m_csSetupList);
	if(m_vSetupList.size() <= 0)
		return FALSE;
	std::vector<SETUPSTRUCT>::iterator itor = m_vSetupList.begin();
	if(itor != m_vSetupList.end())
	{
		setup = (*itor);
		m_vSetupList.erase(itor);
		return TRUE;
	}
	return FALSE;
	/*for(vector<CString>::iterator itor = m_vSetupList.begin();
		itor != m_vSetupList.end();++itor)
	{

	}*/
}

BOOL CSetupThread::RunExe(CStdString strPath)
{
	BOOL bRes = FALSE;
	DWORD dwExitCode = -1;

	SHELLEXECUTEINFO shexec = {0};
	shexec.fMask  = SEE_MASK_NOCLOSEPROCESS;
	shexec.cbSize = sizeof(SHELLEXECUTEINFO);
	shexec.nShow  = SW_SHOW;
	shexec.lpVerb = L"open";
	shexec.lpFile =  strPath.GetData();
	shexec.lpParameters = L"";

	if(FALSE == CheckFileExist(strPath.GetData(),FALSE))
		return FALSE;

	if(ShellExecuteEx(&shexec))
	{
		int nWaitSecond = 0;
		while(WAIT_TIMEOUT == WaitForSingleObject(shexec.hProcess, 1000) &&
		m_ExitEvent != NULL && WAIT_TIMEOUT == WaitForSingleObject(m_ExitEvent,1))
		{
			if(nWaitSecond < m_nSetupTimeout)
			{
				nWaitSecond++;
			}
			else
				break;
		}
		
		BOOL bHr = GetExitCodeProcess(shexec.hProcess, &dwExitCode);
		if(nWaitSecond >= m_nSetupTimeout)
		{
			if(bHr && dwExitCode == STILL_ACTIVE)
				bRes = FALSE;
			else
			{
				OutputDebugString(L"\nSetupTimeout\n");
				bRes = FALSE;
			}
			
		}
		else if(bHr == TRUE && dwExitCode == 0)
		{
			SetFileAttributes(strPath.GetData(), ~FILE_ATTRIBUTE_READONLY&GetFileAttributes(strPath.GetData()));
			DeleteFile(strPath.GetData());
			/*OutputDebugString(L"\nDeleteFile");
			OutputDebugString(strPath);
			OutputDebugString(L"\n");
			//HANDLE hfile = CreateFile(strPath.GetData(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL);
			if(FALSE == DeleteFile(strPath.GetData()))
			{
				DWORD dwError = GetLastError();
				TCHAR sz[MAX_PATH] = {0};
				_itow(dwError,sz,MAX_PATH);
				MessageBox(NULL,strPath.GetData(),sz,MB_OK);
			}*/
			bRes = TRUE;
		}
	}

	return bRes;
}

BOOL CSetupThread::CheckFileExist(LPCTSTR pstrFileName, BOOL bCanZero)
{
	BOOL Result = FALSE;
	WIN32_FIND_DATA FileData={0}; 
	HANDLE hSearch;
	hSearch = FindFirstFile(pstrFileName, &FileData); 
	if (hSearch != INVALID_HANDLE_VALUE) 
	{ 
		if (bCanZero || FileData.nFileSizeLow || FileData.nFileSizeHigh)
			Result = TRUE;
	}

	FindClose(hSearch);
	return Result;
}

void CSetupThread::Pause()
{
	m_bPause = true;
}

void CSetupThread::Resume()
{
	m_bPause = false;
}